import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosPromise, AxiosError } from 'axios'
import { ResultVo, AxiosServiceConfig } from './types/axios-config'
import { useSpinStore, useLoginInfoStore } from '@/store'
import { message } from 'ant-design-vue'

class HttpService {

    private baseUrl: string = import.meta.env.VITE_BASE_URL ? import.meta.env.VITE_BASE_URL : '/';

    private timeout: number = 60 * 60 * 100;

    private instance!: AxiosInstance;

    private axiosServiceConfig: AxiosServiceConfig;

    private spinState = useSpinStore()

    private loginInfoState = useLoginInfoStore()


    constructor(axiosServiceConfig: AxiosServiceConfig) {
        this.axiosServiceConfig = axiosServiceConfig;
        this.instance = axios.create({
            baseURL: this.baseUrl,
            timeout: this.timeout
        });
        this.setInterceptors()
    }
    // 设置拦截器
    private setInterceptors() {
        // 请求拦截器
        this.instance.interceptors.request.use((config: AxiosRequestConfig<any>) => {
            // 是否显示loading
            if (this.axiosServiceConfig.isLodding) {
                this.spinState.$reset() //恢复默认值
                this.spinState.setSpinSimpleOption(true, this.axiosServiceConfig.loadingText)
            }
            // 设置请求头中携带token
            const token = this.loginInfoState.getToken
            if (this.axiosServiceConfig.isToken && token && config.headers) {
                config.headers['Authorization'] = token
            }
            return config
        }, (error) => {
            console.error("请求发送错误" + error)
            // 对请求错误做些什么
            return Promise.resolve(error);
        })

        // 响应拦截器
        this.instance.interceptors.response.use((res: AxiosResponse<ResultVo<any>>): any => {
            // 是否显示loading
            if (this.axiosServiceConfig.isLodding) {
                this.spinState.setSpinSimpleOption(false, this.axiosServiceConfig.loadingText)
            }
            // 请求响应状态码200 
            if (res.status === 200) {
                const resultData: ResultVo<any> = res.data
                // TODO: 后端自定义code 为2000则为正常  需要对登录过期做处理
                if (resultData.code === 2000) {
                    let msg = resultData.msg
                    if (this.axiosServiceConfig.isSuccessMsg) {
                        if (this.axiosServiceConfig.successMsg) {
                            msg = this.axiosServiceConfig.successMsg
                        }
                        message.success(msg)
                    }
                    return Promise.resolve(resultData)
                } else {
                    let msg = resultData.msg
                    if (this.axiosServiceConfig.isErrorMsg) {
                        if (this.axiosServiceConfig.errorMsg) {
                            msg = this.axiosServiceConfig.errorMsg
                        }
                        message.error(msg)
                    }
                    return Promise.resolve(resultData)
                }
            } else {
                let msg = '服务器内部错误'
                if (this.axiosServiceConfig.isErrorMsg) {
                    if (this.axiosServiceConfig.errorMsg) {
                        msg = this.axiosServiceConfig.errorMsg
                    }
                    message.error(msg)
                }
                const result: ResultVo<any> = {
                    code: res.status,
                    msg: msg,
                    data: res.data
                }
                return Promise.resolve(result)
            }
        }, (error: AxiosError<ResultVo<any>>) => {
            // 是否显示loading
            if (this.axiosServiceConfig.isLodding) {
                this.spinState.setSpinSimpleOption(false, this.axiosServiceConfig.loadingText)
            }
            let msg = ''
            switch (error.response?.status) {
                case 400:
                    msg = "请求错误(400)";
                    break;
                case 401:
                    msg = "未授权，请重新登录(401)";
                    // TODO: 这里可以做清空storage并跳转到登录页的操作
                    break;
                case 403:
                    msg = "拒绝访问(403)";
                    break;
                case 404:
                    msg = "请求出错(404)";
                    break;
                case 408:
                    msg = "请求超时(408)";
                    break;
                case 500:
                    msg = "服务器错误(500)";
                    break;
                case 501:
                    msg = "服务未实现(501)";
                    break;
                case 502:
                    msg = "网络错误(502)";
                    break;
                case 503:
                    msg = "服务不可用(503)";
                    break;
                case 504:
                    msg = "网络超时(504)";
                    break;
                case 505:
                    msg = "HTTP版本不受支持(505)";
                    break;
                default:
                    msg = `连接出错(${error.response?.status})!`;
            }
            if (this.axiosServiceConfig.isErrorMsg) {
                if (this.axiosServiceConfig.errorMsg) {
                    msg = this.axiosServiceConfig.errorMsg
                }
                message.error(msg)
            }
            const result: ResultVo<any> = {
                code: Number(error.response?.status) || 5515,
                msg: msg,
                data: error.response?.data
            }
            return Promise.resolve(result);
        })
    }

    public getIntenent<T = any>(): Promise<ResultVo<T>> {
        return this.instance.request(this.axiosServiceConfig)
    }

}

export default function HttpServiceInstance<T>(axiosServiceConfig: AxiosServiceConfig): Promise<ResultVo<T>> {
    return new HttpService(axiosServiceConfig).getIntenent()
}

